package org.halk.listener;

import org.halk.config.CustomHolidayProperties;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.monitor.FileAlterationListener;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.system.ApplicationHome;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 * 监听加节日自定义配置文件
 *
 * @Author halk
 * @Date 2023/4/25 21:20
 **/
@Component
@Slf4j
public class FileMonitorListener implements FileAlterationListener {

    @Resource
    private CustomHolidayProperties customHolidayProperties;

    /**
     * 自定义节假日配置文件路径
     */
    @Value("${predict.holiday.path}")
    private String holidayPath;

    /**
     * 自定义节假日配置文件内容
     */
    @Value("${predict.holiday.content}")
    private String holidayContent;

    /**
     * 配置文件名称
     */
    private static final String HOLIDAY_CONFIG_NAME = "customHoliday.properties";

    @PostConstruct
    public void fileMonitor() {
        if (!StringUtils.hasText(holidayPath)) {
            //配置路径为空，使用默认位置：jar包同级目录config文件下
            ApplicationHome home = new ApplicationHome(FileMonitorListener.class);
            String jarPath = home.getSource().getParentFile().toString();
            holidayPath = jarPath + "/config";
        }
        File file = new File(holidayPath.endsWith("/") ? holidayPath : (holidayPath + "/") + HOLIDAY_CONFIG_NAME);
        if (file.exists()) {
            reloadFile(file);
        }else {
            createFile(file);
        }
        try {
            // 构造观察类主要提供要观察的文件或目录，当然还有详细信息的filter
            FileAlterationObserver observer = new FileAlterationObserver(holidayPath);
            // 为观察对象添加收听对象
            observer.addListener(this);
            // 配置Monitor，第一个参数单位是毫秒，是监听间隔；第二个参数就是绑定我们之前的观察对象。
            FileAlterationMonitor fileMonitor = new FileAlterationMonitor(5000, observer);
            // 启动监听
            fileMonitor.start();
        } catch (Exception e) {
            log.error("fileMonitor start error", e);
        }
    }

    @Override
    public void onStart(FileAlterationObserver fileAlterationObserver) {
        log.info("file monitor start");
    }

    @Override
    public void onDirectoryCreate(File directory) {
        log.info("directory create. path:{}", directory.getPath());
    }

    @Override
    public void onDirectoryChange(File directory) {
        log.info("directory change. path:{}", directory.getPath());
    }

    @Override
    public void onDirectoryDelete(File directory) {
        log.info("directory delete. path:{}", directory.getPath());
    }

    @Override
    public void onFileCreate(File file) {
        log.info("file create. path:{}", file.getPath());
    }

    @Override
    public void onFileChange(File file) {
        log.info("file change. path:{}", file.getPath());
        if (file.getAbsolutePath().contains(HOLIDAY_CONFIG_NAME)) {
            log.info("自定义日期配置文件改变！path:{}", file.getPath());
            reloadFile(file);
        }
    }

    @Override
    public void onFileDelete(File file) {
        log.info("file delete. path:{}", file.getPath());
    }

    @Override
    public void onStop(FileAlterationObserver observer) {
        log.info("file monitor stop");
    }

    /**
     * 处理改变的文件
     *
     * @param file
     */
    private void reloadFile(File file) {
        Properties properties = new Properties();
        try {
            BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
            //使用properties对象加载输入流
            properties.load(bufferedReader);
            //根据key获取对应的value
            String value = properties.getProperty("customHoliday");
            this.customHolidayProperties.coverList(value);
            log.info("节假日自定义配置文件重新加载! customHoliday: {}", value);
            bufferedReader.close();
        } catch (IOException e) {
            log.error("节假日自定义配置文件重新加载失败！", e);
        }
    }

    /**
     * 创建配置文件，填充内容
     *
     * @param file
     */
    private void createFile(File file) {
        log.info("自定义节假日名称配置文件不存在，创建文件！");
        try {
            FileUtils.writeStringToFile(file, holidayContent, "UTF-8");
            //加载内容到属性中
            reloadFile(file);
        } catch (IOException e) {
            log.error("创建节假日自定义配置文件失败！", e);
        }
    }
}
